package com.zch.starter.sentinel.springboot.starter.filter;

import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 继承了CommonFilter 主要是CommonFilter不支持排除某个url 的限流
 */
public class ExcludePathCommonFilter extends CommonFilter {
    private final List<String> excludePaths = new CopyOnWriteArrayList<>();

    /**
     * 设置要排除的 URL 路径（支持动态更新）
     */
    public void setExcludePaths(String... paths) {
        excludePaths.clear();
        if (paths != null) {
            excludePaths.addAll(Arrays.asList(paths));
        }
    }

    /**
     * 添加单个排除路径
     */
    public void addExcludePath(String path) {
        if (path != null) {
            excludePaths.add(path);
        }
    }

    /**
     * 移除某个排除路径
     */
    public void removeExcludePath(String path) {
        excludePaths.remove(path);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String path = httpRequest.getRequestURI();

        // 检查是否匹配排除路径
        if (isExcludedPath(path)) {
            // 直接放行，不经过 Sentinel 拦截
            chain.doFilter(request, response);
            return;
        }

        // 不匹配排除路径，走父类的 Sentinel 拦截逻辑
        super.doFilter(request, response, chain);
    }

    /**
     * 检查路径是否匹配排除规则
     */
    public boolean isExcludedPath(String path) {
        for (String excludePath : excludePaths) {
            if(StringUtils.isBlank(excludePath)){
                continue;
            }
            if (path.startsWith(excludePath) || matchesAntPath(path, excludePath)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 简单的 Ant 风格路径匹配（支持 /** 通配符）
     */
    private boolean matchesAntPath(String path, String pattern) {
        if (pattern.endsWith("/**")) {
            String basePattern = pattern.substring(0, pattern.length() - 3);
            return path.startsWith(basePattern);
        }
        return false;
    }
}
